package com.example.robertluozizhao.framecollectdemo.view.custom;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * @author luo_zi_zhao
 * @version V1.0 内部拦截法容器
 * @FileName com.example.robertluozizhao.framecollectdemo.view.custom
 * @date 2019/7/15 9:50
 */

public class HorizontalScrollViewGroup02 extends ViewGroup {
    private final static String TAG = "HorizontalScrollview";
    private Scroller mScroller;
    private float mDownX;

    float interceptDownX = 0;
    float interceptDownY = 0;
    private VelocityTracker mVelocityTracker;//速度跟踪

    private int mChildWidth;
    private int mChildeIndex;
    private int mChildCount;

    public HorizontalScrollViewGroup02(Context context) {
        this(context, null);
    }

    public HorizontalScrollViewGroup02(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mScroller = new Scroller(getContext());
        mVelocityTracker = VelocityTracker.obtain();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childCount = getChildCount();

        //1.先测量子view
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        //2.自身测量
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

        if (childCount == 0) {
            //子view 数量为0 宽高为父容器剩余空间
            setMeasuredDimension(sizeWidth, sizeWidth);
        } else if (modeHeight == MeasureSpec.AT_MOST && modeWidth == MeasureSpec.AT_MOST) {
            View childAt = getChildAt(0);
            //横向排布效果 默认取第一个view的高度
            setMeasuredDimension(childCount * childAt.getMeasuredWidth(), childAt.getMeasuredHeight());
        } else if (modeHeight == MeasureSpec.AT_MOST) {
            setMeasuredDimension(sizeWidth, getChildAt(0).getHeight());
        } else if (modeWidth == MeasureSpec.AT_MOST) {
            setMeasuredDimension(childCount * getChildAt(0).getMeasuredWidth(), sizeHeight);
        } else {
            setMeasuredDimension(sizeWidth, sizeWidth);
        }
    }

    /**
     * 确定子view位置
     *
     * @param changed
     * @param l
     * @param t
     * @param r
     * @param b
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childLeft = 0;
        mChildCount = getChildCount();

        for (int i = 0; i < mChildCount; i++) {
            View childAt = getChildAt(i);
            int measuredWidth = childAt.getMeasuredWidth();
            mChildWidth = measuredWidth;
            //宽：累计子view的宽度  高：取子view高度
            childAt.layout(childLeft, 0, childLeft + childAt.getMeasuredWidth(), childAt.getMeasuredHeight());
            childLeft += childAt.getMeasuredWidth();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = ev.getX();
                Log.d(TAG, "onTouchEvent: mDownX:" + mDownX + ",moveX:" + moveX);
                //为负数：scrollBy移动的是控件里的内容，是相对滑动方向的反方向
                scrollBy((int) -(moveX - mDownX), 0);
                break;
            case MotionEvent.ACTION_UP:
                //优化：为了滑动到view边界
                measureVelocity(ev);
                break;
        }
        mDownX = ev.getX();
        return true;
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean isIntercept = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //不能拦截Down事件,后续事件自己处理，导致子View永远处理不了事件
                break;
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                //设置为true:当子View 调用 requestDisallowInterceptTouchEvent(false)申请父容器不拦截事件为（false）
                //此时此事件交回给父容器，所以父容器需要自己消耗掉返回true。

                /*疑点：这里move事件已经拦截了，那怎么会传递后续事件到子View呢？
                 子View需要在down事件的时候调用requestDisallowInterceptTouchEvent(true),
                 表示父容器down事件之后的系列事件将不要拦截（这里跟事件分发流程有点不同）*/
                isIntercept = true;
                break;
        }
        return isIntercept;
    }

    private void smoothScrollBy(int dx) {
        mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
        invalidate();
    }

    /**
     * 模板写法
     */
    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    private void measureVelocity(MotionEvent ev) {
        mVelocityTracker.addMovement(ev);
        int scroll = getScrollX();
        //1秒内滑动
        mVelocityTracker.computeCurrentVelocity(1000);
        float xVelocity = mVelocityTracker.getXVelocity();
        if (Math.abs(xVelocity) > 50) {
            mChildeIndex = xVelocity > 0 ? mChildeIndex - 1 : mChildeIndex + 1;
        } else {
            mChildeIndex = (scroll + mChildWidth / 2) / mChildWidth;
        }
        mChildeIndex = Math.max(0, Math.min(mChildeIndex, mChildCount - 1));
        int dx = mChildeIndex * mChildWidth - scroll;
        smoothScrollBy(dx);
        mVelocityTracker.clear();
    }

}
